/*
 * Copyright (C), 2007-2018, 铭师堂教育科技有限公司
 * FileName: WorkSheetController.java
 * Author:   zhaoyi
 * Date:     2018年11月10日 下午4:49:04
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.secsbrain.cloudconsole.web.controller;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.secsbrain.cloudconsole.biz.constant.EnumDefinition;
import com.secsbrain.cloudconsole.dal.model.WorkSheet;
import com.secsbrain.cloudconsole.dal.model.WorkSheetOps;
import com.secsbrain.common.utils.DateTimeUtils;
import com.secsbrain.frame.lock.Callback;
import com.secsbrain.frame.lock.DistributedLockTemplate;
import com.secsbrain.sso.core.SsoHelper;
import com.secsbrain.sso.model.dto.system.UserDetailDTO;
import com.secsbrain.sso.service.provider.HttpRequestValueProvider;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.plugins.Page;
import com.secsbrain.cloudconsole.biz.IWorkSheetOpsService;
import com.secsbrain.cloudconsole.biz.IWorkSheetService;
import com.secsbrain.cloudconsole.biz.constant.RoleCodeConstants;
import com.secsbrain.cloudconsole.biz.utils.WorkSheetUtils;
import com.secsbrain.common.ErrorCodeEnum;
import com.secsbrain.common.ResponseResult;

/**
 * 工单控制层
 *
 * @author zhaoyi
 * 
 */
@RequestMapping("/workSheet")
@RestController
public class WorkSheetController {

	private static final Logger logger = LoggerFactory.getLogger(WorkSheetController.class);
	
	@Autowired
	private DistributedLockTemplate distributedLockTemplate;

	@Autowired
	private IWorkSheetService workSheetService;

	@Autowired
	private IWorkSheetOpsService workSheetOpsService;
	 
	@Resource(name="appcode")
	HttpRequestValueProvider<String> appCodeValueProvider;
	
	@Resource(name="roleCode")
	HttpRequestValueProvider<String> roleCodeValueProvider;

	/**
	 * @api {GET} /workSheet/query 查询工单列表
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {String} [code] 工单编号 
	 * @apiParam {String} [description] 描述
	 * @apiParam {String} [startDate] 开始时间，格式yyyy-MM-dd
	 * @apiParam {String} [endDate] 结束时间，格式yyyy-MM-dd
	 * @apiParam {Number[]} [statusArray] 状态
	 * @apiParam {String} [creatorName] 提交人
	 * @apiParam {String} [opsName] 处理人
	 * @apiParam {Number} [itype] 类型 
	 * 
	 * @apiSuccess {Object[]} data 数据列表
	 * @apiSuccess {Number} data.id 工单ID
	 * @apiSuccess {Boolean} data.code 工单编号
	 * @apiSuccess {Boolean} data.description 描述
	 * @apiSuccess {Number} data.ilevel 优先级  0-一般，1-重要，2-紧急
	 * @apiSuccess {String} itype 类型：-1为其他，0-服务器 ，1-自动化发布，2-域名，3-修改配置，4-软件安装 
	 * @apiSuccess {String} data.creatorName 提交人
	 * @apiSuccess {String} data.opsName 处理人
	 * @apiSuccess {String} data.executorName 构建人
	 * @apiSuccess {Date} data.createTime 提交时间
	 * @apiSuccess {Number} data.istatus 状态：0-待受理 ，1-待处理，2-待确认，3-已关闭
	 */
	@RequestMapping(value = "/query", method = RequestMethod.GET)
	public ResponseResult<Page<WorkSheet>> query(WorkSheet workSheet,
                                             HttpServletRequest httpServletRequest,
                                             @RequestParam(value = "page", defaultValue = "1")Integer page,
                                             @RequestParam(value = "limit", defaultValue = "10")Integer limit) {
		if(StringUtils.isNotEmpty(workSheet.getStartDate())&&StringUtils.isNotEmpty(workSheet.getEndDate())){
			workSheet.setStartDate(workSheet.getStartDate()+" 00:00:00");
			workSheet.setEndDate(workSheet.getEndDate()+" 23:59:59");
		}
		return new ResponseResult(workSheetService.queryWorkSheet(workSheet,
				appCodeValueProvider.getValue(httpServletRequest),
				roleCodeValueProvider.getValue(httpServletRequest),page, limit));
	}

	/**
	 * @api {GET} /workSheet/detail/{id} 查询工单详情
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number} id 工单id
	 * 
	 * @apiSuccess {Number} id 工单ID
	 * @apiSuccess {Boolean} code 工单编号
	 * @apiSuccess {Boolean} description 描述
	 * @apiSuccess {Number} ilevel 优先级  0-一般，1-重要，2-紧急
	 * @apiSuccess {String} itype 类型    -1为其他，0-服务器 ，1-自动化发布，2-域名，3-修改配置，4-软件安装 
	 * @apiSuccess {String} creatorName 提交人
	 * @apiSuccess {String} opsName 处理人
	 * @apiSuccess {String} executorName 构建人
	 * @apiSuccess {Date} createTime 提交时间
	 * @apiSuccess {Number} istatus 状态：0-待受理 ，1-待处理，2-待确认，3-已关闭
	 * @apiSuccess {String} fileVname 文件名称
	 * 
	 * @apiSuccess (其他通用){String} workOpsCommon   		其他通用对象
	 * @apiSuccess (其他通用){String} workOpsCommon.hostIp 服务器IP
	 * 
	 * @apiSuccess (服务器申请){String} workServerApply   服务器申请对象
	 * @apiSuccess (服务器申请){String} workServerApply.hostName 主机标识
	 * @apiSuccess (服务器申请){String} workServerApply.env 应用环境
	 * @apiSuccess (服务器申请){String} workServerApply.imageName 镜像
	 * @apiSuccess (服务器申请){Date} 	 workServerApply.dueDate 到期时间
	 * @apiSuccess (服务器申请){String} workOpsCommon.hostIp 服务器IP
	 * 
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess 	自动化发布对象
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.appName 应用名
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.systemType 系统类型
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.typeName 分类名称
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.vlevel 应用等级
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.gitUrl git地址
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.remark 应用描述
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.ownerName 开发负责人
	 * @apiSuccess (自动化发布新接入){String} workDeployAccess.qualityName 质量负责人
	 * 
	 * @apiParam (自动化发布其他){Object} workDeployOther        	自动化接入对象
	 * @apiParam (自动化发布其他){String} workDeployOther.appName    应用名
	 * 
	 * @apiSuccess (cloud分组发布接入){String} workBootGroupAccess 	cloud分组发布对象
	 * @apiSuccess (cloud分组发布接入){String} workBootGroupAccess.sfEnv 分组环境 
	 * @apiSuccess (cloud分组发布接入){String} workBootGroupAccess.appName 应用名称
	 * @apiSuccess (cloud分组发布接入){String} workBootGroupAccess.eurekaUrl eureka地址 
	 * @apiSuccess (cloud分组发布接入){Number} workBootGroupAccess.port 端口号
	 * @apiSuccess (cloud分组发布接入){String} workBootGroupAccess.applicationName spring应用名
	 * @apiSuccess (cloud分组发布接入){Number} workBootGroupAccess.waitTime 下线后等待时间（秒）
	 * 
	 */
	@RequestMapping(value = "/detail/{id}", method = RequestMethod.GET)
	public ResponseResult<WorkSheet> detail(@PathVariable("id") Long id) {
		Assert.notNull(id,"工单ID不能为空");
		return new ResponseResult(workSheetService.queryWorkSheetDetail(id));
	}
	
	/**
	 * @api {GET} /workSheet/queueCount/{id} 查询排队中工单的数量
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number}  id  工单id
	 * 
	 * @apiSuccess {Number} data 排队中工单的数量
	 * 
	 */
	@RequestMapping(value = "/queueCount/{id}", method = RequestMethod.GET)
	public ResponseResult<?> queueCount(@PathVariable("id") Long id) {
		Assert.notNull(id,"工单ID不能为空");
		
		WorkSheet workSheet=workSheetService.selectById(id);
		Assert.notNull(workSheet, "没有找到相应的工单");

		WorkSheet workSheetParam=new WorkSheet();
		workSheetParam.setOpsId(workSheet.getOpsId());
		workSheetParam.setIstatus(EnumDefinition.WorkSheetStatus.DEAL.getCode());
		int count=workSheetService.selectCount(workSheetParam);
		return new ResponseResult(count);
	}
	
	/**
	 * @api {GET} /workSheet/todoCount 查询待办工单数量
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiSuccess {Number} data 工单待办数量
	 * 
	 */
	@RequestMapping(value = "/todoCount", method = RequestMethod.GET)
	public ResponseResult<?> todoCount() {
		UserDetailDTO userDetailDTO= SsoHelper.currentUser();
		int totalCount=0;
		if(WorkSheetUtils.hasIncludeRole(userDetailDTO.getUserRoleList(), RoleCodeConstants.DEVELOPER)){
			WorkSheet workSheetParam=new WorkSheet();
			workSheetParam.setCreatorId(userDetailDTO.getId());
			workSheetParam.setIstatus(EnumDefinition.WorkSheetStatus.FINISH.getCode());
			int count=workSheetService.selectCount(workSheetParam);
			totalCount+=count;
		}
		
		if(WorkSheetUtils.hasIncludeRole(userDetailDTO.getUserRoleList(), RoleCodeConstants.OPS)){
			WorkSheet workSheetParam=new WorkSheet();
			workSheetParam.setOpsId(userDetailDTO.getId());
			workSheetParam.setIstatus(EnumDefinition.WorkSheetStatus.DEAL.getCode());
			int count1=workSheetService.selectCount(workSheetParam);
			totalCount+=count1;
			
			WorkSheet workSheetParam2=new WorkSheet();
			workSheetParam2.setIstatus(EnumDefinition.WorkSheetStatus.CREATE.getCode());
			int count2=workSheetService.selectCount(workSheetParam2);
			totalCount+=count2;
		}

		return new ResponseResult(totalCount);
	}
	
	/**
	 * @api {GET} /workSheet/dealTime/{id} 查询工单处理时间
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number} id 工单id
	 * 
	 * @apiSuccess {Number} data 工单处理时间（分）
	 * 
	 */
	@RequestMapping(value = "/dealTime/{id}", method = RequestMethod.GET)
	public ResponseResult<Long> dealTime(@PathVariable("id") Long id) {
		Assert.notNull(id,"工单ID不能为空");
		
		WorkSheet workSheet=workSheetService.selectById(id);
		Assert.notNull(workSheet, "没有找到相应的工单");
		
		Assert.isTrue(EnumDefinition.WorkSheetStatus.FINISH.getCode().equals(workSheet.getIstatus())||EnumDefinition.WorkSheetStatus.CLOSE.getCode().equals(workSheet.getIstatus()), "工单状态不正确");
		
		WorkSheetOps workSheetOpsParam=new WorkSheetOps();
		workSheetOpsParam.setOpsId(workSheet.getOpsId());
		workSheetOpsParam.setSheetId(workSheet.getId());
		List<WorkSheetOps> workSheetOpsList=workSheetOpsService.selectList(workSheetOpsParam);
		if(CollectionUtils.isEmpty(workSheetOpsList)){
			return new ResponseResult(0L);
		}
		WorkSheetOps workSheetOps=workSheetOpsList.get(0);

		long diff = DateTimeUtils.minitesOfTwo(workSheetOps.getCreateTime(), workSheetOps.getUpdateTime());
		return new ResponseResult(diff);
	}

	/**
	 * @api {POST} /workSheet/commit 提交工单
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {String}  description 描述
	 * @apiParam {Number}  ilevel 优先级
	 * @apiParam {Number}  itype  类型 
	 * @apiParam {Number}  [subType]  子类型 
	 * @apiParam {File}  [file]       文件
	 * 
	 * @apiParam (其他通用){Object} workOpsCommon        其他通用对象
	 * @apiParam (其他通用){String} workOpsCommon.hostIp 服务器IP
	 * 
	 * @apiParam (服务器申请){Object} workServerApply        	服务器申请对象
	 * @apiParam (服务器申请){String} workServerApply.hostName 	主机标识
	 * @apiParam (服务器申请){String} workServerApply.env 		应用环境
	 * @apiParam (服务器申请){String} workServerApply.imageName 镜像
	 * @apiParam (服务器申请){String} workServerApply.dueDateStr 到期时间：yyyy-MM-dd格式
	 * 
	 * @apiParam (自动化发布新接入){Object} workDeployAccess        	自动化接入对象
	 * @apiParam (自动化发布新接入){String} workDeployAccess.appId    应用Id
	 * @apiParam (自动化发布新接入){String} workDeployAccess.systemType 系统类型
	 * @apiParam (自动化发布新接入){String} workDeployAccess.btypeId 分类ID
	 * @apiParam (自动化发布新接入){String} workDeployAccess.vlevel 应用等级
	 * @apiParam (自动化发布新接入){String} workDeployAccess.gitUrl git地址
	 * @apiParam (自动化发布新接入){String} workDeployAccess.remark 应用描述
	 * @apiParam (自动化发布新接入){String} workDeployAccess.ownerId 开发负责人ID
	 * @apiParam (自动化发布新接入){String} workDeployAccess.qualityId 质量负责人ID
	 * 
	 * @apiParam (自动化发布其他){Object} workDeployOther        	自动化接入对象
	 * @apiParam (自动化发布其他){String} workDeployOther.appId    应用Id
	 * 
	 * @apiParam (cloud分组发布接入){String} workBootGroupAccess 	cloud分组发布对象
	 * @apiParam (cloud分组发布接入){String} workBootGroupAccess.sfEnv 分组环境 
	 * @apiParam (cloud分组发布接入){String} workBootGroupAccess.appId 应用ID
	 * @apiParam (cloud分组发布接入){String} workBootGroupAccess.eurekaUrl eureka地址 
	 * @apiParam (cloud分组发布接入){Number} workBootGroupAccess.port 端口号
	 * @apiParam (cloud分组发布接入){String} workBootGroupAccess.applicationName spring应用名
	 * @apiParam (cloud分组发布接入){Number} workBootGroupAccess.waitTime 下线后等待时间（秒）
	 * 
	 */
    @RequestMapping(value = "/commit", method = RequestMethod.POST)
    public ResponseResult<?> commit(HttpServletRequest httpServletRequest,WorkSheet workSheet) throws Exception {
    	logger.debug("提交工单。。。参数：{}",JSON.toJSONString(workSheet));
    	
		Assert.hasText(workSheet.getDescription(), "工单描述不能为空");
		Assert.notNull(workSheet.getIlevel(),"工单优先级不能为空");
		Assert.notNull(workSheet.getItype(),"工单类型不能为空");
		Assert.isTrue(!(workSheet.getIlevel()<0||workSheet.getIlevel()>2), "工单优先级不正确");		
		Assert.isTrue(!(workSheet.getItype()<-1||workSheet.getItype()>4), "工单类型不正确");		

		if(EnumDefinition.WorkSheetType.SERVER.getCode().equals(workSheet.getItype())){
			Assert.notNull(workSheet.getSubType(),"工单子类型不能为空");
			if(EnumDefinition.ServerSubType.APPLY.getCode().equals(workSheet.getSubType())){
				Assert.hasText(workSheet.getWorkServerApply().getEnv(), "应用环境不能为空");
				Assert.hasText(workSheet.getWorkServerApply().getImageName(), "镜像不能为空");
				Assert.hasText(workSheet.getWorkServerApply().getHostName(), "主机标识不能为空");
				Assert.hasText(workSheet.getWorkServerApply().getDueDateStr(), "使用到期日不能为空");
				Assert.isTrue(DateTimeUtils.truncatedCompareTo(new Date(),DateTimeUtils.parseStringToDate(
				        workSheet.getWorkServerApply().getDueDateStr()+" 00:00:00"), Calendar.DAY_OF_MONTH)<0, "使用到期日不能早于今天");
			}else{
				Assert.hasText(workSheet.getWorkOpsCommon().getHostIp(), "服务器IP不能为空");
			}
		}else if(EnumDefinition.WorkSheetType.DEPLOY.getCode().equals(workSheet.getItype())){
			Assert.notNull(workSheet.getSubType(),"工单子类型不能为空");
			if(EnumDefinition.DeploySubType.APPNEW.getCode().equals(workSheet.getSubType())){
				Assert.hasText(workSheet.getWorkDeployAccess().getAppName(), "应用名称不能为空");
				Assert.hasText(workSheet.getWorkDeployAccess().getGitUrl(), "git地址不能为空");
				Assert.notNull(workSheet.getWorkDeployAccess().getOwnerId(), "开发负责人不能为空");
				Assert.notNull(workSheet.getWorkDeployAccess().getQualityId(), "质量负责人不能为空");
				Assert.hasText(workSheet.getWorkDeployAccess().getRemark(), "应用描述不能为空");
				Assert.hasText(workSheet.getWorkDeployAccess().getSystemType(), "应用类型不能为空");
				Assert.hasText(workSheet.getWorkDeployAccess().getVlevel(), "应用级别不能为空");
				Assert.notNull(workSheet.getWorkDeployAccess().getBtypeId(), "应用分类不能为空");
			}else if(EnumDefinition.DeploySubType.CLOUDGROUP.getCode().equals(workSheet.getSubType())){
				Assert.notNull(workSheet.getWorkBootGroupAccess().getAppId(), "发布应用不能为空");
				Assert.hasText(workSheet.getWorkBootGroupAccess().getSfEnv(), "分组环境不能为空");
				Assert.hasText(workSheet.getWorkBootGroupAccess().getEurekaUrl(), "eurekaUrl不能为空");
				Assert.notNull(workSheet.getWorkBootGroupAccess().getPort(), "应用端口号不能为空");
				Assert.hasText(workSheet.getWorkBootGroupAccess().getApplicationName(), "spring应用名不能为空");
				Assert.notNull(workSheet.getWorkBootGroupAccess().getWaitTime(), "下线等待时间不能为空");
			}else{
				Assert.notNull(workSheet.getWorkDeployOther().getAppId(), "发布应用不能为空");
			}
		}else if(EnumDefinition.WorkSheetType.DOMAIN.getCode().equals(workSheet.getItype())){
		}else if(EnumDefinition.WorkSheetType.CONFIG.getCode().equals(workSheet.getItype())|| EnumDefinition.WorkSheetType.INSTALL.getCode().equals(workSheet.getItype())){
			Assert.hasText(workSheet.getWorkOpsCommon().getHostIp(), "服务器IP不能为空");
		}
		
    	return (ResponseResult<?>) distributedLockTemplate.execute("commit_worksheet_"+SsoHelper.currentUser().getId(), 0, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				try {
					MultipartHttpServletRequest request = (MultipartHttpServletRequest) httpServletRequest;
					MultipartFile file=request.getFile("file");
					if(file!=null){
//				    	StorePath storePath=storageClient.uploadFile(file.getInputStream(), file.getSize(), "worsheet"+UUID.randomUUID().toString(), null);
//				    	workSheet.setFilePath(storePath.getFullPath());
//				    	workSheet.setFileVname(file.getOriginalFilename());
					}
			    	
					workSheetService.createWorkSheet(workSheet,appCodeValueProvider.getValue(httpServletRequest));
				}catch (Exception e) {
					logger.error("",e);
					return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),e.getMessage());
				}
				return new ResponseResult();
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),"重复提交");
			}

    	});
    }
    
    /**
	 * @api {POST} /workSheet/claim 认领工单
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number}  id   工单ID
	 */
    @RequestMapping(value = "/claim", method = RequestMethod.POST)
    public ResponseResult<?> claim(HttpServletRequest httpServletRequest,@RequestBody WorkSheet workSheet) {
		Assert.notNull(workSheet.getId(),"工单ID不能为空");
    	
    	return (ResponseResult<?>) distributedLockTemplate.execute("claim_worksheet_"+workSheet.getId(), 0, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				try {
			    	workSheetService.claimWorkSheet(workSheet.getId(),appCodeValueProvider.getValue(httpServletRequest));
				}catch (Exception e) {
					logger.error("",e);
					return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),e.getMessage());
				}
				return new ResponseResult();
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),"重复提交");
			}

    	});
    }
    
    /**
	 * @api {POST} /workSheet/finish 完成工单（结单）
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number}  id   工单ID
	 * @apiParam {String}  message 消息
	 */
    @RequestMapping(value = "/finish", method = RequestMethod.POST)
    public ResponseResult<?> finish(HttpServletRequest httpServletRequest,@RequestBody WorkSheet workSheet) {
    	Assert.notNull(workSheet.getId(),"工单ID不能为空");
        Assert.hasText(workSheet.getMessage(), "沟通内容不能为空");
        Assert.hasText(workSheet.getMessage().trim(), "沟通内容不能为空");

    	return (ResponseResult<?>) distributedLockTemplate.execute("finish_worksheet_"+workSheet.getId(), 0, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				try {
			    	workSheetService.finishWorkSheet(workSheet.getId(),workSheet.getMessage(),appCodeValueProvider.getValue(httpServletRequest));
				}catch (Exception e) {
					logger.error("",e);
					return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),e.getMessage());
				}
				return new ResponseResult();
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),"重复提交");
			}

    	});
    }
    
    /**
	 * @api {POST} /workSheet/transfer 转移工单
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number}  id   工单ID
	 * @apiParam {Number}  opsId 要转移的处理人ID
	 */
    @RequestMapping(value = "/transfer", method = RequestMethod.POST)
    public ResponseResult<?> transfer(HttpServletRequest httpServletRequest,@RequestBody WorkSheet workSheet) {
    	
    	
    	return (ResponseResult<?>) distributedLockTemplate.execute("transfer_worksheet_"+workSheet.getId(), 0, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				try {
			    	workSheetService.transferWorkSheet(workSheet.getId(), workSheet.getOpsId(),appCodeValueProvider.getValue(httpServletRequest));
				}catch (Exception e) {
					logger.error("",e);
					return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),e.getMessage());
				}
				return new ResponseResult();
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),"重复提交");
			}

    	});
    }
    
    /**
	 * @api {POST} /workSheet/close 关闭工单
	 * 
	 * @apiGroup Worksheet
	 * 
	 * @apiParam {Number}  id   工单ID
	 */
    @RequestMapping(value = "/close", method = RequestMethod.POST)
    public ResponseResult<?> close(@RequestBody WorkSheet workSheet) {
    	Assert.notNull(workSheet.getId(),"工单ID不能为空");

    	return (ResponseResult<?>) distributedLockTemplate.execute("close_worksheet_"+workSheet.getId(), 0, new Callback() {

			@Override
			public Object onGetLock() throws InterruptedException {
				try {
			    	workSheetService.closeWorkSheet(workSheet.getId());
				}catch (Exception e) {
					logger.error("",e);
					return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),e.getMessage());
				}
				return new ResponseResult();
			}

			@Override
			public Object onTimeout() throws InterruptedException {
				return new ResponseResult<>(ErrorCodeEnum.ERROR_COMMON_SYSTEM.getCode(),"重复提交");
			}

    	});
    }
    
    /**
     * 
     * @api {GET} /workSheet/downloadFile/{id} 下载文件
     * @apiGroup  Worksheet 
     * 
     * @apiParam {Number} id  工单ID
     * 
     */
    @RequestMapping(value = "/downloadFile/{id}", method = RequestMethod.GET)
    public void downloadFile(@PathVariable("id") Long id, HttpServletRequest httpServletRequest, HttpServletResponse response) throws IOException{
    	logger.debug("下载工单文件开始。。。id:{}", id);
    	
    	WorkSheet workSheet=workSheetService.selectById(id);
		Assert.notNull(workSheet, "没有找到相应的工单");

		String path=workSheet.getFilePath();
		Assert.hasText(path, "没有找到相应的工单文件");
		
		UserDetailDTO userDetailDTO=SsoHelper.currentUser();
		Assert.isTrue(userDetailDTO.getId().equals(workSheet.getCreatorId())
				||WorkSheetUtils.hasIncludeRole(userDetailDTO.getUserRoleList(), RoleCodeConstants.OPS), "权限不足");

    	String group=path.substring(0,path.indexOf("/"));
    	String path1=path.substring(path.indexOf("/")+1,path.length());
    	
//    	storageClient.downloadFile(group, path1, new DownloadCallback<byte[]>() {
//
//			@Override
//			public byte[] recv(InputStream ins) throws IOException {
//
//				response.setHeader("Content-disposition", "attachment;filename=" + getFileName(httpServletRequest, workSheet.getFileVname()));
//				response.setContentType("application/force-download");// 设置强制下载不打开
//				byte[] buffer = new byte[1024];
//				BufferedInputStream bis = null;
//				try {
//					bis = new BufferedInputStream(ins);
//					OutputStream os = response.getOutputStream();
//					int i = bis.read(buffer);
//					while (i != -1) {
//						os.write(buffer, 0, i);
//						i = bis.read(buffer);
//				 	}
//				} catch (Exception e) {
//				    logger.error("",e);
//				} finally {
//				    if (bis != null) {
//				        try {
//				            bis.close();
//				        } catch (IOException e) {
//						    logger.error("",e);
//				        }
//				    }
//				    if (ins != null) {
//				        try {
//				        	ins.close();
//				        } catch (IOException e) {
//						    logger.error("",e);
//				        }
//				    }
//				}
//				return null;
//			}
//		});
    	 
    }
    
    public static String getFileName(HttpServletRequest request, String fileName) {
        final String userAgent = request.getHeader("USER-AGENT");
        String finalFileName = null;
        try {
            if (StringUtils.contains(userAgent, "MSIE")) {// IE浏览器
                finalFileName = URLEncoder.encode(fileName, "UTF8");
            } else if (StringUtils.contains(userAgent, "Mozilla")) {// google,火狐浏览器
                finalFileName = new String(fileName.getBytes("UTF8"), "ISO8859-1");
            } else {
                finalFileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
            }
        } catch (UnsupportedEncodingException e) {
        }
        return finalFileName;
    }

}
